using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using Rotempco.Core.Web.Logic;
using Rotempco.Core.Web.CRUD.Interfaces;
using Rotempco.Core.Web.CRUD.Logic;
using Rotempco.Core.Web.CRUD.Events;
using Rotempco.Core.Web.CRUD.Objects.Enums;
using Rotempco.Core.Web.Objects.Enums;
using Rotempco.Core.ORM.Logic;
using Rotempco.Core.Web.CRUD.Objects;

namespace Rotempco.Core.Web.CRUD.ACRUD
{

    public abstract class ACRUDEdit<TCRUDObject, TPrimaryKey> : AAdminMaster
        where TCRUDObject : class, new()
        where TPrimaryKey : struct
    {
        public delegate void AfterSaveDelegate();
        public event AfterSaveDelegate AfterSaveEvent;

        protected override void OnLoad(EventArgs e)
        {
            CRUDEditMaster.SaveEvent += new SaveEvent(button_SaveEvent);

            if (!IsPostBack)
                DataBindControls();

            CRUDEditMaster.SetReturnUrl(GetReturnUrl());
            CRUDEditMaster.SetDisableReturnToListAfterSaveEvent(DisableReturnToListAfterSaveEvent());

            base.OnLoad(e);
        }


        public virtual bool DisableReturnToListAfterSaveEvent()
        {
            return false;
        }

        public virtual string GetReturnUrl()
        {
            return UrlLogic.GotoUrl(UrlLogic.GetStaticBaseUrl(), excludeUrlParameterEnums: new[] { UrlParameterEnum.Id });
        }

        public virtual TCRUDObject GetById(TPrimaryKey id)
        {
            return ManagerInstanceHelper.GetManagerInstance<TCRUDObject, TPrimaryKey>().GetById(id);
        }

        public virtual object GetObjectId()
        {
            return UrlLogic.GetIdFromUrlAsString();
        }

        public virtual Nullable<TPrimaryKey> GetId()
        {
            object obj = GetObjectId();
            if (obj == null)
                return default(TPrimaryKey);

            return (TPrimaryKey)DBNullHelper.ToType(obj, typeof(TPrimaryKey));
        }

        public virtual TCRUDObject GetNewInstance()
        {
            return new TCRUDObject();
        }

        public virtual void Persist(TCRUDObject tDomainObject)
        {
            ManagerInstanceHelper.GetManagerInstance<TCRUDObject, TPrimaryKey>().WriteToDB(tDomainObject);
        }

        public virtual void FillObject(TCRUDObject tDomainObject)
        {
            WebFormFiller.FillObject<TCRUDObject>(tDomainObject, this.Page);
        }

        public virtual string ValidateObject(TCRUDObject tDomainObject)
        {
            return null;
        }

        public virtual void DataBindControls()
        {
            TCRUDObject domainObject = GetObjectInstance();
            WebFormFiller.FillForm<TCRUDObject>(domainObject, this);
        }

        private ICRUDEdit CRUDEditMaster
        {
            get
            {
                return (Master as ICRUDEdit);
            }

        }

        protected bool button_SaveEvent()
        {
            return Persist();
        }

        public bool Persist()
        {
            TCRUDObject tDomainObject = GetObjectInstance();

            FillObject(tDomainObject);

            string errorString = ValidateObject(tDomainObject);
            if (errorString != null)
            {
                CRUDEditMaster.SetErrorMessage(errorString);
                return false;
            }

            Persist(tDomainObject);

            if (AfterSaveEvent != null)
                AfterSaveEvent();

            return true;
        }


        private TCRUDObject ObjectInstance { get; set; }

        public TCRUDObject GetObjectInstance()
        {
            if (ObjectInstance != null)
                return ObjectInstance;

            object id = GetObjectId();

            if (id != null && GetId().HasValue)
                ObjectInstance = GetById(GetId().Value);
            else
                ObjectInstance = GetNewInstance();

            return ObjectInstance;
        }

       
    }
}